import logging
import os.path
import sys
import warnings

import pandas as pd
from numpy import double

from gauss_reversals import gauss_inverse, gauss_forward

warnings.filterwarnings('ignore')

# False：表示不包含带号  True：表示包含带号
flag = False

# 定义坐标系信息
coordinates = {
    '1954北京坐标系': {
        '长半轴': 6378245.0,
        '扁率': 1 / 298.3,
        '中央经线': 117.0
    },
    '1980西安坐标系': {
        '长半轴': 6378140.0,
        '扁率': 1 / 298.2570,
        '中央经线': 114.0
    },
    '2000国家大地坐标系': {
        '长半轴': 6378137.0,
        '扁率': 1 / 298.257222101,
        '中央经线': 121.464444
    }
}


def check_data(input_path):
    """
    用于传入数据，判断是东北还是北东格式数据
    :param input_path: 输入文件的路径
    :return:正确格式更换后的数据
    """
    df = []
    # 根据输入的文件类型读入数据
    file_extension = os.path.splitext(input_path)[1]
    if file_extension == '.csv':
        df = pd.read_csv(input_path, header=None)
    elif file_extension == '.xlsx':
        df = pd.read_excel(input_path, header=None)
    else:
        error_exit("请输入.csv或.xlsx格式的文件")

    temp_df0 = df.iloc[:, 0].copy().rename('点号')
    # 分别检查第一列和第二列数据的首行  符合要求的话将列数据保存至temp_df中
    temp_df1 = check_first_line(df, 1)
    temp_df2 = check_first_line(df, 2)

    # 将z列写入数据，如果为空，默认值为0
    if len(df.columns) > 3:
        temp_df3 = df.iloc[:, 3].copy().rename('Z')
    else:
        temp_df3 = pd.Series([0] * len(df), name='Z')

    # 拼接检查的数据。东北格式错乱时，直接自行进行格式更换
    result = pd.concat([temp_df0, temp_df1, temp_df2, temp_df3], axis=1)
    return result


def check_east_north(df):
    col_name1 = df.columns[1]
    col_name2 = df.columns[2]
    if col_name1 == 'X' and col_name2 == 'Y':
        print("数据是北东格式")
    elif col_name1 == 'Y' and col_name2 == 'X':
        print("数据是东北格式")


def check_first_line(df, colomn):
    """
    检查第一行数据，根据第一行判断是东北还是北东
    :param df:
    :param colomn:
    :return:
    """
    # 获取第一行第一列单个数据的长度
    col_length = len(str(int(df.iloc[0][colomn])))
    # 将第一列数据存入temp_df
    temp_df = df.iloc[:, colomn].copy()
    # 判断第一列是X还是Y数据
    match col_length:
        case 6:
            temp_df.rename('Y', inplace=True)
        case 8:
            temp_df.rename('Y', inplace=True)
        case 7:
            temp_df.rename('X', inplace=True)
        # case _:
        #     outlog("第一行数据位数有误")
        #     error_exit("")
    return temp_df


def check_digits(dataframe):
    """
    检查所有数据的范围是否正确
    检查所有数据的位数是否正确
    :param dataframe:
    :return:
    """
    # 定义一个标签记录是否含有带号
    global flag
    # 循环遍历DataFrame的指定列
    for col in dataframe.columns:
        # 跳过点号列
        if col != '点号':
            for index, value in enumerate(dataframe[col]):
                integer_digits = len(str(int(value)))
                if col == 'X' and integer_digits == 7:
                    if value > 6000000 or value < 2000000:
                        outlog("数据范围有误，出现在" + str(index + 1) + "行" + col + "坐标")
                elif col == 'Y' and integer_digits == 6:
                    if value > 700000 or value < 300000:
                        outlog("数据范围有误，出现在" + str(index + 1) + "行" + col + "坐标")
                elif col == 'Y' and len(str(value)) == 8:
                    flag = True  # flag标签，true代表有带号
                    last_six_digits = double(str(int(value))[-6:])
                    if last_six_digits > 700000 or last_six_digits < 300000:
                        outlog("数据范围有误，出现在" + str(index + 1) + "行" + col + "坐标")
                elif (col == 'X' or col == 'Y') and (integer_digits != 6 or integer_digits != 7 or integer_digits != 8):
                    outlog("数据位数有误，出现在" + str(index + 1) + "行" + col + "坐标")


def check_central_meridian(df, coorSys_text, central_meridian):
    """
    检查带号
    :param df: 数组
    :return:
    """
    # coorSys_text = sys.argv[3]  # 接收来自前端的坐标系文字
    # central_meridian = double(sys.argv[4])  # 接收来自前端的中央子午线
    tape_number = int(central_meridian / 6) + 1  # 记录中央子午线所在的带号
    if coorSys_text == "自定义椭球":
        # print("当前坐标系中央子午线所在带号为" + str(tape_number))
        if flag:
            print("数据包含带号")
            for index, value in enumerate(df['Y']):
                meridian = int(str(value)[-8:-6])  # 记录数据所在的带号
                # 循环判别每一个数据的带号是否正确
                if tape_number != meridian:
                    outlog("数据带号与中央子午线不匹配，出现在" + str(index + 1) + "行")
        else:
            print("数据不包含带号")
    else:
        temp_num = coordinates[coorSys_text]["中央经线"]  # 获取已经预定好的中央经线
        tape_number = int(temp_num / 6) + 1  # 记录中央子午线所在的带号
        if flag:
            print("数据包含带号")
            for index, value in enumerate(df['Y']):
                meridian = int(str(value)[-8:-6])  # 记录数据所在的带号
                # 循环判别每一个数据的带号是否正确
                if tape_number != meridian:
                    outlog("数据带号与中央子午线不匹配，出现在" + str(index + 1) + "行")
        else:
            print("数据不包含带号")


# 输出错误信息并结束进程
def error_exit(msg):
    print(msg)
    sys.exit()


# 将信息输出到所选择的日志
def outlog(msg):
    print(msg)
    log_file = sys.argv[2]
    logging.basicConfig(filename=log_file)
    logging.error(msg)


def write_data(data):
    # 将数据写入excel文件，如果文件不存在则创建一个新文件，已存在则覆盖
    # 指定excel文件路径
    excel_path = '临时坐标.xlsx'
    # 判断文件是否存在
    if os.path.isfile(excel_path):
        # 文件存在，删除原文件
        os.remove(excel_path)
    # 将数据写入CSV文件
    data.to_excel(excel_path, index=False)


if __name__ == '__main__':
    src_file_path = "G:\pythonProject\surveying_mapping\data\测试数据(数据位数有误).xlsx"  # sys.argv[1]  # 源文件路径
    src_coorSys_text = "1954北京坐标系"  # sys.argv[3]  # 源坐标系文字
    src_central_meridian = 117  # double(sys.argv[4])  # 源中央子午线
    src_a = 1  # double(sys.argv[5])  # 源长半轴
    src_rf = 1  # double(sys.argv[6])  # 源扁率

    data = check_data(src_file_path)
    # 检查数据位数是否正确
    check_digits(data)
    # 检查东北、北东格式
    check_east_north(data)
    # 检查中央子午线和带号是否匹配
    check_central_meridian(data, src_coorSys_text, src_central_meridian)
    # 写入临时数据供使用
    write_data(data)
